package com.aco.party.service.system;

import com.aco.party.dao.custom.PostsDao;
import com.aco.party.dao.custom.RoleDao;
import com.aco.party.dao.custom.UserDao;
import com.aco.party.dao.custom.UserRoleDao;
import com.aco.party.enums.UserStatusEnum;
import com.aco.party.model.po.User;
import com.aco.party.model.po.UserExample;
import com.aco.party.model.po.UserRole;
import com.aco.party.model.po.UserRoleExample;
import com.aco.party.model.vo.PostsParam;
import com.aco.party.model.vo.UserListResponse;
import com.aco.party.model.vo.UserQueryParam;
import com.aco.party.model.vo.UserRoleVo;
import com.aco.party.model.vo.common.PageParam;
import com.aco.party.model.vo.common.UserWithRoleVo;
import com.aco.party.util.ConfigResource;
import com.aco.party.util.MailUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class UserService {
	@Resource
    private UserDao userDao;
	
	@Resource
	private UserRoleDao userRoleDao;

	@Resource
	private RoleDao roleDao;

	@Resource
	private PostsDao postsDao;

	@Resource
	private TaskExecutor taskExecutor;

	public UserWithRoleVo getCurrentUser() {
		Object obj = SecurityUtils.getSubject().getPrincipal();
		if(obj == null) return null;
        final Long currentUserId = (Long)obj;
            return getUserWithRole(currentUserId);
    }

    public void createUser(User user) {
		if(StringUtils.isNotEmpty(user.getPassword())){
			user.setPassword( new Sha256Hash(user.getPassword()).toHex() );
		}else {
			String initPwd = ConfigResource.getSystemProperty("init_pwd");
			if (StringUtils.isEmpty(initPwd)) initPwd = "123456";
			user.setPassword( new Sha256Hash(initPwd).toHex() );
		}
		if(StringUtils.isEmpty(user.getNickName())) {
			user.setNickName("Morketing用户");
		}
		user.setCreateTime(new Date());
        userDao.insertSelective(user);

		final String email = user.getEmail();
		taskExecutor.execute(new Runnable() {
			@Override
			public void run() {
				MailUtil.sendMail(email, "Morketing 恭喜您注册成功！", "恭喜您注册成功！如果您没有设置密码，则您的初始密码是" +
						ConfigResource.getSystemProperty("init_pwd")+"，请您及时更改密码！谢谢！");
			}
		});
    }
    
    public List<User> getAllUsers() {
        return userDao.getAll();
    }

	public int getUserCount() {
		return userDao.getAll().size();
	}
    
    public User getUser(Long id) {
        return userDao.selectByPrimaryKey(id);
    }

	public UserWithRoleVo getUserWithRole(Long id) {
		return userDao.getUserWithRole(id);
	}
	public User findUserByName(String username) {
		UserExample example = new UserExample();
		UserExample.Criteria criteria = example.createCriteria();
		criteria.andUsernameEqualTo(username);
		List<User> users = userDao.selectByExample(example);
		if(users != null && users.size() > 0) {
			return users.get(0);
		}
		return null;
	}

	public User findUserByEmail(String email) {
		UserExample example = new UserExample();
		UserExample.Criteria criteria = example.createCriteria();
		criteria.andEmailEqualTo(email);
		List<User> users = userDao.selectByExample(example);
		if(users != null && users.size() > 0) {
			return users.get(0);
		}
		return null;
	}

	public User findUserByOpenId(String openId) {
		UserExample example = new UserExample();
		UserExample.Criteria criteria = example.createCriteria();
		criteria.andExtra4EqualTo(openId);
		List<User> users = userDao.selectByExample(example);
		if(users != null && users.size() > 0) {
			return users.get(0);
		}
		return null;
	}

    public void delete(Long id) {
        userDao.deleteByPrimaryKey(id);
    }

    public void updateUser(User user) {
		user.setUpdateTime(new Date());
        userDao.updateByPrimaryKeySelective(user);
    }

	public void increaseRoles(Long userId, Long roleId) {
		if(userId != null && roleId != null){
			UserRole userRole = new UserRole();
			userRole.setUserId(userId);
			userRole.setRoleId(roleId);
			userRoleDao.insert(userRole);
		}
	}
	public void decreaseRoles(Long userId, Long roleId) {
		if(userId!=null&&roleId!=null){
			UserRoleExample example = new UserRoleExample();
			example.createCriteria().andUserIdEqualTo(userId).andRoleIdEqualTo(roleId);
			example.setDistinct(true);
			List<UserRole> userRoles = userRoleDao.selectByExample(example);
			if(userRoles != null && userRoles.size() > 0){
				userRoleDao.deleteByPrimaryKey(userRoles.get(0).getId());
			}
		}
	}

	public List<UserListResponse> getUsersByParam(PageParam pageParam){
		List<UserListResponse> responses = new ArrayList<>();
		List<User> users = userDao.getUsers(pageParam);
		List<String> roleStr = new ArrayList<>();
		if(users != null && users.size() > 0){
			for (User user : users){
				List<UserRoleVo> roles = userRoleDao.getRolesByUserId(user.getId());
				for(UserRoleVo role : roles){
					roleStr.add(role.getRoleDesc());
				}
				UserListResponse response = new UserListResponse();
				BeanUtils.copyProperties(user,response);
				response.setRoleName(StringUtils.join(roleStr,","));
				response.setStatusName(UserStatusEnum.getUserStatus(user.getStatus()).getDesc());
				responses.add(response);
				roleStr.clear();
			}
		}
		return responses;
	}

	public List<UserListResponse> getAuthorsByParam(PageParam pageParam, UserQueryParam param){
		List<UserListResponse> responses = new ArrayList<>();
		List<UserWithRoleVo> vos = userDao.getUserVosByParam(param, pageParam);
		UserListResponse author;
		PostsParam postsParam = new PostsParam();
		if(vos != null){
			for (UserWithRoleVo vo : vos){
				author = new UserListResponse();
				BeanUtils.copyProperties(vo,author);
				author.setStatusName(UserStatusEnum.getUserStatus(vo.getStatus()).getDesc());
				postsParam.setAuthorId(vo.getId());
				postsParam.setStatuses(new ArrayList<>(Collections.singleton("审核通过")));
				author.setPostCount(postsDao.getTotal(postsParam).longValue());
				responses.add(author);
			}
		}
		return responses;
	}

	public int getAuthorsCountByParam(UserQueryParam param){
		return userDao.getUsersCountByParam(param);
	}

	public List<User> getUsersByParam(UserQueryParam param){
		return userDao.getUsersByParam(param);
	}

	public int getCountByParam(String date){
		return userDao.getCountByParam(date);
	}
}
